﻿using System;
using ModuloSoporte.Excepciones;
using Siscont.Contabilidad.Excepciones;
using Entidades;

namespace Siscont.Contabilidad
{
    /// <summary>
    /// Cuenta.
    /// </summary>
    public class Cuenta
    {
        #region Constantes

        /// <summary>
        /// Nivel en que las cuentas son imputables.
        /// </summary>
        public const int NivelFinal = 5;

        #endregion

        #region Atributos

        public string Id
        {
            get { return Datos.Idcuenta; }
        }

        public bool Imputable
        {
            get { return Datos.Imputable; }
        }

        public string Nombre
        {
            get { return string.Format("{0}. {1}", Datos.Idcuenta, Datos.Descripcion); }
        }

        public int Nivel
        {
            get
            {
                return Cuenta.CalcularNivel(Id);
            }
        }

        Entidades.Entity_cuenta datos;
        public Entidades.Entity_cuenta Datos
        {
            get { return datos; }
            set { datos = value; }
        }

        #endregion

        #region Ctor

        public Cuenta(Entidades.Entity_cuenta datos)
        {
            Datos = datos;
        }

        #endregion

        /// <summary>
        /// Calcula el nivel de una cuenta en base a su código.
        /// </summary>
        /// <param name="codigo"></param>
        /// <returns></returns>
        public static int CalcularNivel(string codigo)
        {
            return Math.Min(codigo.Length, 5);
        }

        /// <summary>
        /// Valida la cuenta para determinar si es apta para dar altas.
        /// </summary>
        public void ValidarDatosAlta()
        {
            ValidarDatos();

            var db = CapaDatos.Datos.Manejador[typeof(Entity_cuenta)];
            var cuenta = this.Datos;

            if (db.Existe(cuenta))
                throw new ExcepcionValorInvalido(
                    string.Format("La cuenta \"{0}\" ya existe.",
                    cuenta.Idcuenta));
        }

        /// <summary>
        /// Valida la cuenta para determinar si es apta para dar altas.
        /// </summary>
        public void ValidarDatosEdicion()
        {
            var cuenta = this.Datos;
            if (!cuenta.Editable)
                throw new Excepcion("La cuenta modificada no es editable.");

            ValidarDatos();
        }

        /// <summary>
        /// Valida los datos de la cuenta.
        /// </summary>
        private void ValidarDatos()
        {
            if (string.IsNullOrEmpty(datos.Descripcion))
            {
                throw new Excepcion("El campo \"Descripción\" se encuentra vacío.", "Campo incorrecto");
            }
            else
            {
                try
                {
                    int.Parse(this.Id);
                }
                catch
                {
                    throw new ExcepcionValorInvalido("El número de la cuenta contiene caracteres inválidos o está vacío.");
                }


                var db = CapaDatos.Datos.Manejador[typeof(Entidades.Entity_cuenta)];

                if (CalcularNivel(datos.Idcuenta) > 1)
                {
                    var test = new Entidades.Entity_cuenta
                    {
                        Idcuenta = datos.Idcuenta.Substring(0, Math.Min(4, datos.Idcuenta.Length - 1)),
                        Ejercicio_codejercicio = datos.Ejercicio_codejercicio,
                        Ejercicio_empresa_idempresa = datos.Ejercicio_empresa_idempresa
                    };

                    if (!db.Existe(test))
                    {
                        throw new Excepcion("No existe una cuenta padre para la subcuenta a agregar.");
                    }
                }
            }
        }

        public override string ToString()
        {
            return this.Nombre;
        }
    }
}
